home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 4591 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  9.3 KB

  1. Path: goanna.cs.rmit.EDU.AU!not-for-mail
  2. From: ok@goanna.cs.rmit.EDU.AU (Richard A. O'Keefe)
  3. Newsgroups: comp.lang.ada,comp.lang.c++,comp.lang.c,comp.lang.modula3,comp.lang.modula2
  4. Subject: Re: Hungarian notation
  5. Date: 31 Jan 1996 15:57:12 +1100
  6. Organization: Comp Sci, RMIT, Melbourne, Australia
  7. Message-ID: <4emsr8$hib@goanna.cs.rmit.EDU.AU>
  8. References: <30C40F77.53B5@swsbbs.com> <4bd <4cc2b2$11jq@navajo.gate.net> <4cud8f$gup@news.netvision.net.il> <4dttefINNo29@keats.ugrad.cs.ubc.ca> <Pine.HPP.3.91.960122145028.27524A-100000@clear.cs.byu.edu> <dewar.822407363@schonberg> <Pine.HPP.3.91.960124153551.24374C-100000@zeezrom.cs.byu.edu> <4e7ifl$et3@goanna.cs.rmit.EDU.AU> <Pine.HPP.3.91.960129133429.8419C-100000@foggy.cs.byu.edu>
  9. NNTP-Posting-Host: goanna.cs.rmit.edu.au
  10. NNTP-Posting-User: ok
  11. X-Newsreader: NN version 6.5.0 #0 (NOV)
  12.  
  13. Douglas Evan Cook <cookd@cs.byu.edu> writes:
  14. >I'm sure I'm missing your point,
  15. >but it is clear that you are also missing mine.
  16.  
  17. Perhaps we have a terminology problem.
  18. Part of the problem is that you keep on talking about 'typedef', which is
  19. a C concept having nothing to do with abstract data types.  All that
  20.     typedef ... identifier ...;
  21. does in C is to establish identifier as a *synonym* for an existing type
  22. that can be expressed without it.
  23.  
  24. Let me briefly describe a language that has abstract data types:  Mercury.
  25. A Mercury module (like an Ada package)
  26.  - can import ABSTRACT types, CONCRETE types, constants, and predicates
  27.    (think 'routines') from other modules
  28.  - can define new types, new constants, and new predicates
  29.  - can export selected predicates and constants, and types with OR WITHOUT
  30.    their representations.
  31.  
  32. For example, suppose I have a "set(T)" data type implemented by a "set.m"
  33. module.  This module will export
  34.     - the fact that there *exists* a type constructor called set(T)
  35.     - *NO* information at all about the representation of that type
  36.     - a collection of predicates some of which may have parameters of
  37.       type set(X).
  38. Suppose I also have a "node" data type implemented by a "node.m" module.
  39. This module will export
  40.     - the fact that there *exists* a type constructor called 'node'
  41.     - *NO* information at all about the representation of that type
  42.     - a collection of predicates some of which may have parameters of
  43.       type 'node'.
  44. Then I can implement a "graph" data type in a module "graph.h".
  45. INSIDE the module
  46.     :- type graph = pair(set(node), set(pair(node))).
  47. I can do this even though *nobody* processing this file has any idea of
  48. the representation of 'node' or 'set', not the human reader, and not even
  49. the compiler.
  50.  
  51. Now this is data abstraction.  "graph.m" uses 'node' and 'set(T)' without
  52. knowing _anything at all_ about those types except their names and the
  53. names-and-parameter-profiles of the operations on them.
  54.  
  55. C's "typedef" (and C/ObjC/C++ are the only languages I know having a
  56. "typedef" keyword) is by design totally incapable of accomplishing this.
  57.  
  58.  
  59. About saving and restoring abstract values, I wrote:
  60. >> As long as there is a Pack.T'Write and a Pack.T'Read (forgive me if
  61. >> I've got the syntax a bit wrong, I'm still learning about Ada 95
  62. >> streams) *I* don't have to know what the size of an instance of the
  63. >> type is in the file.  The size appears explicitly nowhere in my code.
  64.  
  65. to which Douglas Cook replied:
  66.  
  67. >No, but somebody must have written those methods, no?
  68.  
  69. Yes, but those methods are INSIDE the abstraction.  Of *course* operations
  70. defined inside an abstraction have access to the representation of the type.
  71. You appeared to be saying that operations *outside* the abstraction required
  72. this information, which is simply not true (at least in Mercury).
  73.  
  74. >And that somebody needed to know how many bits each data type is, no?
  75.  
  76. No.  And "no" in several senses, what's more.  First of all, it is not
  77. the case that any human being ever needed to be aware of what the number
  78. is.  Second, it is not the case that any human being ever needed to be
  79. in a position where s/he _could_ have computed the number.  Third, you
  80. seem to be assuming that a data type _is_ some definite number of bits,
  81. which is not necessarily true.  (Imagine a Burroughs D-machine implementing
  82. a language where each variable is accessed via a descriptor; a 'number'
  83. variable might actually change its size during execution.)  Fourth, even
  84. if (instances of) a data type _are_ some definite number of bits, it is
  85. not necessarily the case that the compiler know or be able to determine
  86. this when compiling the inside of the abstraction.  (For an example, think
  87. of C++:  if B is a subclass of A, the compiler may be compiling a method
  88. for A which will actually be called at run time with arguments of class B,
  89. which hasn't been written yet; the compiler has no idea whatsoever what
  90. the size of B will be.)
  91.  
  92. >When we changed from 16 bit compiler to 32 bit compiler,
  93. >the data files remained the same.
  94.  
  95. What has that to say to anything?  No god ever wrote on a tablet of stone
  96. that the representation used _inside_ a program had to be the same as the
  97. representation used _outside_, and it very often isn't true.  (For example,
  98. if you use XDR, a 16-bit little-endian integer in an internal data structure
  99. will appear in the external data as a 32-bit big-endian integer.  A program
  100. using XDR doesn't know and doesn't have any reason to care.)
  101.  
  102. >Any code that directly accesses the data structures (which is rare 
  103. >outside of library design) needs to know the data structure.
  104.  
  105. If you have code that directly accesses a data structure, and that code
  106. is not *inside* the abstraction, then you haven't got an abstract data type.
  107.  
  108. >Also, when you are making system calls (in assembler, or when you are
  109. >interfacing with Windows and need to do an API call) you also need to
  110. >do bit level interaction with the data structures.
  111.  
  112. If you *know* what the representation of a data structure is to the bit
  113. level, then it isn't an abstract data type.  Abstraction means HIDING
  114. all that kind of detail.
  115.  
  116. For what it's worth, your claim about making system calls may be true in
  117. some operating systems (it was in TOPS-10, and I have to say that it was
  118. a major nuisance) but not all of them.  For example, in MVS, the assembler
  119. comes with a library of *macros* for all the system calls and data blocks.
  120. The macros take care of packing your symbolically provided information into
  121. the requisite control blocks; I have never known and never had any reason
  122. to know what the bit level structures actually are.  What you are telling
  123. me is that the MVS interface was abstract and the Windows interface isn't.
  124.  
  125. I have the three volume "Osborne Windows Programming Series" by Schildt,
  126. Pappas, and Murray, which lists the Windows API.  I have studied these
  127. volumes from cover to cover, and found no use of ADTs.  Typedefs, yes.
  128. ADTs, no.  Let me quote from one randomly selected section (2 facing pages).
  129.  
  130.     BOOL ClipCursor(CONST RECT *lpcRect);
  131.     [Win16: ClipCursor() returns void.]
  132.  
  133.     typedef struct tagRECT {
  134.         LONG left, top, right, bottom;
  135.     } RECT;
  136.     [Win16: the coordinates are of type 'int']
  137.  
  138.     HCURSOR CopyCUrsor(HINSTANCE hInst, HCURSOR hCursor);
  139.     [Win32: the hInst parameter does not exist.]
  140.  
  141. [pp 504,504 of vol 2; the code example at the top of p505 has bad syntax.]
  142.  
  143. BOOL, RECT, LONG, HCURSOR, HINSTANCE are not abstract data types.
  144.  
  145. (Does it make sense that the coordinates of a RECT are LONG in Win32
  146. and int in Win16, but the coordinates of a POINT are int in both?
  147. That's what the description of GetCursorPos on p509 claims.)
  148.  
  149. >How much clearer can I make this?  SOMEBODY HAS TO MAKE THE 
  150. >ADT's!
  151.  
  152. Yes, of course.  Nobody has disputed that.  But what relevance has it to
  153. anything else you were saying?  
  154.  
  155. >And when you have thousands of different ADT's in a library, you 
  156. >need some unifying typedefs.
  157.  
  158. If the abstract types are *different*, what is it that needs to be
  159. *unified* (made identical)?  And how can typedefs (introducing *new names*
  160. for *existing types*) unify anything, let alone "different ADTs"?
  161.  
  162. >So TYPEDEFS ARE NOT "USELESS" OR BAD CODING PRACTICE!
  163. >Sorry for shouting.  I just wanted to make sure that you saw these points,
  164. >because you seem to have missed them in all of my other messages.
  165.  
  166. I have never argued that typedefs are useless,
  167. or that they are bad coding practice.  Indeed, given C's unusual declaration
  168. syntax, typedefs are of great value.
  169.  
  170. But it doesn't matter how much you shout, you cannot change what a typedef
  171. actually accomplishes:
  172.     - a typedef introduces into the current lexical scope
  173.     - a new identifier that stands for
  174.     - an EXISTING already expressible type.
  175. This has nothing to do with abstract data types.  All it does is let you
  176. use as many *names* as you want for the same *concrete* type.  Yes, you
  177. can say
  178.     #if defined(Win16) && !defined(Win32)
  179.     typedef int foo;
  180.     #elif defined(Win32) && !defined(Win16)
  181.     typedef long foo;
  182.     #else
  183.     #error "Define exactly one of Win16, Win32"
  184.     #endif
  185. But you could in any case have written
  186.     #if defined(Win16) && !defined(Win32)
  187.     #define foo int
  188.     #elif defined(Win32) && !defined(Win16)
  189.     #define foo long
  190.     #else
  191.     #error "Define exactly one of Win16, Win32"
  192.     #endif
  193. It's not the typedef that helps in porting, it's the #if.  Neither typedef
  194. nor #define gives you type abstraction.     C++ namespaces and classes do that.
  195.  
  196. -- 
  197. "conventional orthography is ... a near optimal system for the
  198.  lexical representation of English words." Chomsky & Halle, S.P.E.
  199. Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci.
  200.